from nicegui import ui
import pandas as pd
import plotly.graph_objects as go
from data_processing import load_titanic_data, preprocess_data
from visualization import create_survival_chart, create_age_fare_scatter, create_family_survival

# 全局变量
original_data = None
processed_data = None

# 定义主题颜色
THEME_COLORS = {
    "primary": "#1a3a5f",  # 深蓝色
    "secondary": "#2c6c9c",  # 中蓝色
    "accent": "#4da6ff",  # 亮蓝色
    "success": "#4caf50",  # 绿色
    "warning": "#ff9800",  # 橙色
    "danger": "#f44336",  # 红色
    "light": "#f8f9fa",  # 浅灰色
    "dark": "#212529",  # 深灰色
}


def load_data():
    """加载并预处理数据"""
    global original_data, processed_data

    # 显示加载状态
    with ui.linear_progress().props('indeterminate=true').classes('w-full') as progress:
        ui.notify("正在加载数据...", type='info')

    try:
        train, _ = load_titanic_data()
        if train is not None:
            original_data = train
            processed_data = preprocess_data(train)
            ui.notify("数据加载成功!", type="positive")
            update_dashboard()

            # 数据加载成功后自动应用默认筛选
            apply_filters('全部', '全部', 100)  # 使用单值模式
            filter_status.set_text("当前筛选: 全部数据")

        else:
            ui.notify("数据加载失败，请检查文件路径", type="negative")
    except Exception as e:
        ui.notify(f"数据加载错误: {str(e)}", type="negative")
    finally:
        progress.delete()

def update_dashboard():
    """更新仪表盘内容"""
    if processed_data is None:
        return

    # 创建图表
    survival_chart = create_survival_chart(processed_data)
    scatter_chart = create_age_fare_scatter(processed_data)
    family_chart = create_family_survival(processed_data)

    # 更新UI
    survival_plotly.update_figure(survival_chart)
    survival_plotly_detail.update_figure(survival_chart)
    scatter_plotly.update_figure(scatter_chart)
    family_plotly.update_figure(family_chart)

    # 更新统计信息
    total_passengers = len(processed_data)
    survived = processed_data['Survived'].sum()
    survival_rate = survived / total_passengers * 100

    # 清空并重新创建卡片
    stats_card.clear()
    with stats_card:
        with ui.row().classes('w-full gap-4'):
            # 总乘客数卡片
            with ui.card().classes(
                    'flex-1 p-6 rounded-xl shadow-lg transition-all hover:shadow-xl bg-gradient-to-br from-blue-50 to-blue-100'):
                with ui.column().classes('items-center text-center'):
                    ui.icon('people', size='xl', color=THEME_COLORS["primary"]).classes('mb-2')
                    ui.label('总乘客数').classes('text-sm font-medium text-gray-600')
                    ui.label(str(total_passengers)).classes('text-3xl font-bold mt-1 text-gray-800')

            # 幸存人数卡片
            with ui.card().classes(
                    'flex-1 p-6 rounded-xl shadow-lg transition-all hover:shadow-xl bg-gradient-to-br from-green-50 to-green-100'):
                with ui.column().classes('items-center text-center'):
                    ui.icon('check_circle', size='xl', color=THEME_COLORS["success"]).classes('mb-2')
                    ui.label('幸存人数').classes('text-sm font-medium text-gray-600')
                    ui.label(str(survived)).classes('text-3xl font-bold mt-1 text-gray-800')

            # 存活率卡片
            with ui.card().classes(
                    'flex-1 p-6 rounded-xl shadow-lg transition-all hover:shadow-xl bg-gradient-to-br from-purple-50 to-purple-100'):
                with ui.column().classes('items-center text-center'):
                    ui.icon('show_chart', size='xl', color=THEME_COLORS["accent"]).classes('mb-2')
                    ui.label('存活率').classes('text-sm font-medium text-gray-600')
                    with ui.row().classes('items-baseline'):
                        ui.label(f'{survival_rate:.2f}').classes('text-3xl font-bold text-gray-800')
                        ui.label('%').classes('text-lg text-gray-600')


def apply_filters(pclass, sex, age_range):
    """应用数据筛选 - 修复滑块值处理"""
    if processed_data is None:
        ui.notify("数据尚未加载，请先加载数据", type="warning")
        return

    filtered = processed_data.copy()

    # 应用船舱等级筛选
    if pclass != '全部':
        filtered = filtered[filtered['Pclass'] == int(pclass)]

    # 应用性别筛选
    if sex != '全部':
        gender_map = {'男性': 0, '女性': 1}
        filtered = filtered[filtered['Sex'] == gender_map[sex]]

    # 处理年龄筛选 - 修复这里
    min_age, max_age = 0, 100  # 默认值

    # 检查滑块值的类型
    if isinstance(age_range, (tuple, list)) and len(age_range) == 2:
        # 范围滑块模式
        min_age, max_age = age_range
    elif isinstance(age_range, (int, float)):
        # 单值滑块模式
        min_age, max_age = 0, age_range
    else:
        # 其他情况使用默认值
        ui.notify("年龄范围格式错误，使用默认范围 0-100", type="warning")

    # 应用年龄筛选
    filtered = filtered[(filtered['Age'] >= min_age) & (filtered['Age'] <= max_age)]

    # 检查筛选结果
    if len(filtered) == 0:
        ui.notify("没有找到匹配的数据，请调整筛选条件", type="info")

    # 更新表格
    # 只显示部分关键列
    display_cols = ['PassengerId', 'Survived', 'Pclass', 'Sex', 'Age', 'Fare', 'FamilySize']
    display_df = filtered[display_cols].copy()

    # 转换数值为可读标签
    display_df['Survived'] = display_df['Survived'].map({0: '否', 1: '是'})
    display_df['Sex'] = display_df['Sex'].map({0: '男性', 1: '女性'})

    # 确保数据是字符串格式
    display_df = display_df.astype(str)

    # 更新表格数据
    data_table.options['rowData'] = display_df.to_dict('records')

    # 更新筛选状态标签
    filter_text = f"当前筛选: "
    conditions = []
    if pclass != '全部':
        conditions.append(f"船舱等级={pclass}")
    if sex != '全部':
        conditions.append(f"性别={sex}")
    conditions.append(f"年龄范围={min_age}-{max_age}岁")

    if not conditions:
        filter_text += "全部数据"
    else:
        filter_text += ", ".join(conditions)

    filter_status.set_text(filter_text)

    # 强制更新表格
    data_table.update()

# 设置全局样式
ui.add_head_html(f'''
<style>
    body {{
        font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
        background-color: {THEME_COLORS["light"]};
        color: {THEME_COLORS["dark"]};
    }}
    .nicegui-content {{
        max-width: 1400px;
        margin: 0 auto;
        padding: 20px;
    }}
    .card-title {{
        font-size: 1.25rem;
        font-weight: 600;
        color: {THEME_COLORS["primary"]};
        margin-bottom: 1rem;
    }}
    .chart-container {{
        background-color: white;
        border-radius: 12px;
        box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
        padding: 20px;
        margin-bottom: 24px;
    }}
    .tab-panel {{
        padding: 24px;
    }}
</style>
''')

# 添加自定义favicon
ui.add_head_html('''
<link rel="icon" href="https://cdn-icons-png.flaticon.com/512/4145/4145523.png" type="image/png">
''')

# 创建界面
# 创建界面
with ui.header().classes(
        f'bg-gradient-to-r from-{THEME_COLORS["primary"]} to-{THEME_COLORS["secondary"]} text-white h-20 flex items-center px-6 shadow-lg sticky top-0 z-50'):
    with ui.row().classes('w-full items-center justify-between'):
        # 添加Logo和标题
        with ui.row().classes('items-center gap-4'):
            ui.icon('directions_boat', size='xl', color='white').classes('text-white')
            ui.label('泰坦尼克号数据分析系统').classes('text-2xl font-bold tracking-wide text-white')

        # 修复：确保按钮在右上角
        with ui.row().classes('ml-auto'):  # 使用ml-auto将按钮推到右侧
            ui.button('加载数据',
                      on_click=load_data,
                      icon='refresh'
                      ).classes(
                'bg-white text-black hover:bg-blue-100 px-6 py-2 rounded-full shadow-md transition-all font-bold')

with ui.tabs().classes('w-full bg-white h-14 flex items-center shadow-sm mb-6 rounded-lg') as tabs:
    tabs_list = ['概览', '存活率分析', '年龄-票价关系', '家庭规模分析', '数据筛选']
    for tab_name in tabs_list:
        ui.tab(tab_name).classes('px-8 py-3 hover:bg-blue-50 transition rounded-lg font-medium')

with ui.tab_panels(tabs, value='概览').classes('w-full flex-grow'):
    # 概览标签页
    with ui.tab_panel('概览').classes('tab-panel'):
        with ui.column().classes('w-full gap-6'):
            # 统计卡片
            stats_card = ui.row().classes('w-full gap-6')

            # 图表容器
            with ui.card().classes('chart-container w-full'):
                ui.label('乘客存活率多维分析').classes('card-title')
                survival_plotly = ui.plotly(go.Figure()).classes('w-full h-[500px]')

    # 存活率分析标签页
    with ui.tab_panel('存活率分析').classes('tab-panel'):
        with ui.card().classes('chart-container w-full'):
            ui.label('详细存活率分析').classes('card-title')
            survival_plotly_detail = ui.plotly(go.Figure()).classes('w-full h-[600px]')

    # 年龄-票价关系标签页
    with ui.tab_panel('年龄-票价关系').classes('tab-panel'):
        with ui.card().classes('chart-container w-full'):
            ui.label('年龄与票价关系分析').classes('card-title')
            scatter_plotly = ui.plotly(go.Figure()).classes('w-full h-[500px]')

    # 家庭规模分析标签页
    with ui.tab_panel('家庭规模分析').classes('tab-panel'):
        with ui.card().classes('chart-container w-full'):
            ui.label('家庭规模对存活率的影响').classes('card-title')
            family_plotly = ui.plotly(go.Figure()).classes('w-full h-[600px]')

    # 数据筛选标签页
    # 在数据筛选标签页
    with ui.tab_panel('数据筛选').classes('tab-panel'):
        with ui.column().classes('w-full gap-6'):
            # 筛选控制面板
            with ui.card().classes('chart-container w-full'):
                ui.label('数据筛选条件').classes('card-title')
                with ui.row().classes('w-full gap-6 items-center'):
                    pclass_filter = ui.select(
                        options=['全部', '1', '2', '3'],
                        value='全部',
                        label='船舱等级'
                    ).classes('min-w-[120px]')

                    sex_filter = ui.select(
                        options=['全部', '男性', '女性'],
                        value='全部',
                        label='性别'
                    ).classes('min-w-[120px]')

                    with ui.column().classes('min-w-[200px]'):
                        ui.label('年龄范围').classes('text-sm font-medium text-gray-600 mb-1')

                        # 修复：使用带标签的滑块
                        with ui.slider(min=0, max=100, step=1) as slider:
                            slider.set_value(100)  # 初始值设为最大值
                            age_slider = slider  # 保存引用
                            age_label = ui.label('0 - 100 岁')


                            # 更新标签的函数
                            def update_age_label():
                                value = age_slider.value
                                # 检查滑块值的类型
                                if isinstance(value, (tuple, list)) and len(value) == 2:
                                    # 范围滑块模式
                                    min_val, max_val = value
                                    age_label.set_text(f"{min_val} - {max_val} 岁")
                                elif isinstance(value, (int, float)):
                                    # 单值滑块模式
                                    age_label.set_text(f"0 - {value} 岁")
                                else:
                                    # 其他情况
                                    age_label.set_text("0 - 100 岁")


                            # 初始更新
                            update_age_label()
                            # 添加值变化监听
                            age_slider.on_value_change(update_age_label)

                    # 添加重置按钮
                    ui.button('重置',
                              on_click=lambda: (
                                  pclass_filter.set_value('全部'),
                                  sex_filter.set_value('全部'),
                                  age_slider.set_value(100),  # 重置为最大值
                                  update_age_label(),  # 手动更新标签
                                  apply_filters('全部', '全部', 100)  # 使用单值模式
                              ),
                              icon='refresh'
                              ).classes(
                        'bg-gray-500 text-white px-6 py-2 rounded-lg shadow hover:bg-gray-600 transition')

                    ui.button('应用筛选',
                              on_click=lambda: apply_filters(
                                  pclass_filter.value,
                                  sex_filter.value,
                                  age_slider.value
                              ),
                              icon='filter_list'
                              ).classes(
                        'bg-blue-600 text-white px-6 py-2 rounded-lg shadow hover:bg-blue-700 transition')

            # 数据表格
            with ui.card().classes('chart-container w-full'):
                with ui.row().classes('w-full justify-between items-center mb-4'):
                    ui.label('筛选结果').classes('card-title')

                    # 添加显示当前筛选条件的标签
                    global filter_status
                    filter_status = ui.label("当前筛选: 全部数据").classes('text-sm text-gray-600')

                global data_table
                data_table = ui.aggrid({
                    'columnDefs': [
                        {'headerName': '乘客ID', 'field': 'PassengerId', 'width': 100},
                        {'headerName': '是否幸存', 'field': 'Survived', 'width': 100},
                        {'headerName': '船舱等级', 'field': 'Pclass', 'width': 100},
                        {'headerName': '性别', 'field': 'Sex', 'width': 100},
                        {'headerName': '年龄', 'field': 'Age', 'width': 100},
                        {'headerName': '票价', 'field': 'Fare', 'width': 120},
                        {'headerName': '家庭规模', 'field': 'FamilySize', 'width': 120},
                    ],
                    'rowData': [],  # 初始为空
                    'defaultColDef': {
                        'resizable': True,
                        'sortable': True,
                        'filter': True
                    },
                    'rowSelection': 'multiple',
                    'animateRows': True,
                    'pagination': True,
                    'paginationPageSize': 10
                }).classes('w-full h-[500px]')

with ui.footer().classes(
        f'bg-gradient-to-r from-{THEME_COLORS["primary"]} to-{THEME_COLORS["secondary"]} text-white h-16 flex items-center justify-center shadow-inner mt-8 rounded-lg'):
    with ui.row().classes('items-center gap-2'):
        ui.icon('copyright', size='sm', color='white')
        ui.label('2025 大数据编程平台课程设计').classes('text-sm')

# 初始加载
load_data()

# 运行应用
ui.run(
    title='泰坦尼克号数据分析系统',
    dark=False,
    favicon='https://cdn-icons-png.flaticon.com/512/4145/4145523.png',
    binding_refresh_interval=0.5
)